package com.xiaobawang.knowledge.spider.service.impl;

import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.utils.StringUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.xiaobawang.knowledge.spider.config.EmailConfig;
import com.xiaobawang.knowledge.spider.exception.BusinessException;
import com.xiaobawang.knowledge.spider.forest.ChinalifeClient;
import com.xiaobawang.knowledge.spider.mapper.ChinalifeProductMapper;
import com.xiaobawang.knowledge.spider.model.dto.EmailDTO;
import com.xiaobawang.knowledge.spider.model.dto.FileHelperDTO;
import com.xiaobawang.knowledge.spider.model.entity.ChinalifeProduct;
import com.xiaobawang.knowledge.spider.service.ChinalifeProductService;
import com.xiaobawang.knowledge.spider.service.EmailService;
import com.xiaobawang.knowledge.spider.util.FileUtil;
import com.xiaobawang.knowledge.spider.util.GsonUtil;
import com.xiaobawang.knowledge.spider.util.HeaderUtil;
import com.xiaobawang.knowledge.spider.util.UUIDUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static com.xiaobawang.knowledge.spider.constant.ProjectConstant.*;
import static com.xiaobawang.knowledge.spider.util.HeaderUtil.CHINALIFE_HOST;

/**
 * (ChinalifeProduct)表服务实现类
 *
 * @author makejava
 * @since 2025-03-28 13:42:04
 */
@Service("chinalifeProductService")
@Slf4j
public class ChinalifeProductServiceImpl implements ChinalifeProductService {

    @Resource
    ChinalifeClient chinalifeClient;

    private final ChinalifeProductMapper chinalifeProductMapper;

    private final EmailService emailService;

    private final EmailConfig emailConfig;

    public ChinalifeProductServiceImpl(ChinalifeProductMapper chinalifeProductMapper,
                                       EmailService emailService,
                                       EmailConfig emailConfig) {
        this.chinalifeProductMapper = chinalifeProductMapper;
        this.emailService = emailService;
        this.emailConfig = emailConfig;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ChinalifeProduct queryById(String id) {
        return this.chinalifeProductMapper.queryById(id);
    }

    /**
     * 根据条件查询记录
     *
     * @param chinalifeProduct 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ChinalifeProduct> queryAllByLimit(ChinalifeProduct chinalifeProduct) {
        return this.chinalifeProductMapper.queryAllByLimit(chinalifeProduct);
    }

    /**
     * 新增数据
     *
     * @param chinalifeProduct 实例对象
     * @return 实例对象
     */
    @Override
    public ChinalifeProduct insert(ChinalifeProduct chinalifeProduct) {
        this.chinalifeProductMapper.insert(chinalifeProduct);
        return chinalifeProduct;
    }

    /**
     * 修改数据
     *
     * @param chinalifeProduct 实例对象
     * @return 实例对象
     */
    @Override
    public ChinalifeProduct update(ChinalifeProduct chinalifeProduct) {
        this.chinalifeProductMapper.update(chinalifeProduct);
        return this.queryById(chinalifeProduct.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.chinalifeProductMapper.deleteById(id) > 0;
    }

    /**
     * @author synhard
     * @description 每日从官网获取条款信息
     * @date 2025/3/28 14:14
     */
    @Override
    public void getChinalifeProduct(Integer saleType, Integer fileType) {
        // 获取产品列表
        List<ChinalifeProduct> chinalifeProductList = this.getChinalifeProductList(saleType);
        // 获取每个产品文件的字节数组
        List<FileHelperDTO> fileHelperDTOList;
        if (Objects.equals(fileType, CHINALIFE_PRODUCT_TYPE_CLAUSE)) {
            // 条款
            fileHelperDTOList = getChinalifeClauseFileByteArray(chinalifeProductList);
        } else if (Objects.equals(fileType, CHINALIFE_PRODUCT_TYPE_RATE_STABLE)) {
            // 费率
            fileHelperDTOList = getChinalifeRateFileByteArray(chinalifeProductList);
        } else if (Objects.equals(fileType, CHINALIFE_PRODUCT_TYPE_CASH_VALUE)) {
            // 现金价值
            fileHelperDTOList = getChinalifeCashValueFileByteArray(chinalifeProductList);
        } else {
            // 无效类型
            fileHelperDTOList  = new ArrayList<>();
        }
        List<byte[]> fileByteArrList = new ArrayList<>();
        List<String> fileNameList = new ArrayList<>();
        for (FileHelperDTO fileHelperDTO : fileHelperDTOList) {
            fileByteArrList.add(fileHelperDTO.getByteArray());
            fileNameList.add(fileHelperDTO.getFileName());
        }
        // 发送邮件
        try  {
            List<File> zipParts = FileUtil.splitIntoZipFiles(fileByteArrList, fileNameList, 20 * 1024 * 1024);
            for (int i = 0; i < zipParts.size(); i++) {
                File part = zipParts.get(i);
                EmailDTO emailDTO = new EmailDTO();
                emailDTO.setSubject("中国人寿文件（分卷" + (i + 1) + "）");
                emailDTO.setFile(part);
                emailDTO.setContent("此邮件为分卷压缩包，共" + zipParts.size() + "部分，需全部下载后解压");
                emailDTO.setTo(emailConfig.getSupervisorFileReceiver());
                emailDTO.setFrom(emailConfig.getFrom());
                emailService.sendEmail(emailDTO);
                part.delete();
            }
        } catch (Exception ex) {
            log.error("邮件发送失败", ex);
            throw new BusinessException("邮件发送失败: " + ex.getMessage());
        }
    }

    /**
     * @author synhard
     * @description 爬取中国人寿在售产品条款表
     * @date 2025/3/31 16:58
     * @param chinalifeProductList 中国人寿产品信息列表
     * @return java.util.List<byte[]>
     */
    private List<FileHelperDTO> getChinalifeClauseFileByteArray(List<ChinalifeProduct> chinalifeProductList) {
        List<FileHelperDTO> res = new ArrayList<>();
        // 访问每个产品的条款的链接
        for (ChinalifeProduct chinalifeProduct : chinalifeProductList) {
            if (StringUtils.isNotBlank(chinalifeProduct.getClause())) {
                // 获取链接，生成文件对应的字节数组
                try {
                    byte[] bytes = this.chinalifeClient.getChinalifeProductFile(chinalifeProduct.getClause(),
                            HeaderUtil.getHeader(CHINALIFE_HOST, CHINALIFE_HOST));
                    String fileName = chinalifeProduct.getProductname() + "-" + UUIDUtil.generateUUID(4) + ".pdf";
                    FileHelperDTO fileHelperDTO = new FileHelperDTO();
                    fileHelperDTO.setFileName(fileName);
                    fileHelperDTO.setByteArray(bytes);
                    res.add(fileHelperDTO);
                } catch (Exception ex) {
                    log.error(ex.getMessage());
                    throw new BusinessException(ex.getMessage());
                }
            }
        }
        return res;
    }

    /**
     * @author synhard
     * @description 爬取中国人寿在售产品费率表
     * @date 2025/3/31 16:58
     * @param chinalifeProductList 中国人寿产品信息列表
     * @return java.util.List<byte[]>
     */
    private List<FileHelperDTO> getChinalifeRateFileByteArray(List<ChinalifeProduct> chinalifeProductList) {
        List<FileHelperDTO> res = new ArrayList<>();
        // 访问每个产品的条款的链接
        for (ChinalifeProduct chinalifeProduct : chinalifeProductList) {
            if (StringUtils.isNotBlank(chinalifeProduct.getRatestable())) {
                // 获取链接，生成文件对应的字节数组
                try {
                    byte[] bytes = this.chinalifeClient.getChinalifeProductFile(chinalifeProduct.getRatestable(),
                            HeaderUtil.getHeader(CHINALIFE_HOST, CHINALIFE_HOST));
                    String fileName = chinalifeProduct.getProductname() + "-" + UUIDUtil.generateUUID(4) + ".pdf";
                    FileHelperDTO fileHelperDTO = new FileHelperDTO();
                    fileHelperDTO.setFileName(fileName);
                    fileHelperDTO.setByteArray(bytes);
                    res.add(fileHelperDTO);
                } catch (Exception ex) {
                    log.error(ex.getMessage());
                    throw new BusinessException(ex.getMessage());
                }
            }
        }
        return res;
    }

    /**
     * @author synhard
     * @description 爬取中国人寿在售产品现金价值
     * @date 2025/3/31 16:58
     * @param chinalifeProductList 中国人寿产品信息列表
     * @return java.util.List<byte[]>
     */
    private List<FileHelperDTO> getChinalifeCashValueFileByteArray(List<ChinalifeProduct> chinalifeProductList) {
        List<FileHelperDTO> res = new ArrayList<>();
        // 访问每个产品的条款的链接
        for (ChinalifeProduct chinalifeProduct : chinalifeProductList) {
            if (StringUtils.isNotBlank(chinalifeProduct.getCashvalue())) {
                // 获取链接，生成文件对应的字节数组
                try {
                    byte[] bytes = this.chinalifeClient.getChinalifeProductFile(chinalifeProduct.getCashvalue(),
                            HeaderUtil.getHeader(CHINALIFE_HOST, CHINALIFE_HOST));
                    String fileName = chinalifeProduct.getProductname() + "-" + UUIDUtil.generateUUID(4) + ".pdf";
                    FileHelperDTO fileHelperDTO = new FileHelperDTO();
                    fileHelperDTO.setFileName(fileName);
                    fileHelperDTO.setByteArray(bytes);
                    res.add(fileHelperDTO);
                } catch (Exception ex) {
                    log.error(ex.getMessage());
                    throw new BusinessException(ex.getMessage());
                }
            }
        }
        return res;
    }

    /**
     * @param
     * @return List<ChinalifeProduct>
     * @author synhard
     * @description 获取中国人寿产品列表
     * @date 2025/3/28 14:32
     */
    private List<ChinalifeProduct> getChinalifeProductList(int saleType) {
        Timer                  timer      = new Timer();
        List<ChinalifeProduct> resultList = new CopyOnWriteArrayList<>();
        AtomicInteger          page       = new AtomicInteger(1);
        final int              pageSize   = 150;
        CountDownLatch         latch      = new CountDownLatch(1);
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                try {
                    ForestResponse<String> response = chinalifeClient.getChinalifeProductInfoList(
                            pageSize, page.get(),
                            saleType,
                            HeaderUtil.getHeader(CHINALIFE_HOST, CHINALIFE_HOST)
                    );

                    if (!response.isSuccess()) {
                        timer.cancel();
                        throw new BusinessException("请求中国人寿产品列表失败");
                    }

                    JsonObject json = GsonUtil.parseStringToJsonObject(response.getContent());
                    JsonArray  list = GsonUtil.getAsJsonArraySafety(json, "list");
                    if (list == null || list.isEmpty()) {
                        latch.countDown();
                        return;
                    }

                    List<ChinalifeProduct> subList = GsonUtil.getGson().fromJson(
                            list, new TypeToken<List<ChinalifeProduct>>() {
                            }.getType()
                    );
                    resultList.addAll(subList);
                    page.incrementAndGet();
                } catch (Exception e) {
                    log.error("分页请求异常", e);
                    timer.cancel();
                }
            }
        };

        timer.scheduleAtFixedRate(task, 0L, 3000L);

        try {
            latch.await(5, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("线程被中断", e);
        } finally {
            timer.cancel();
        }

        return new ArrayList<>(resultList);
    }


}

